Game Dev

Godot

Impressions
  • I MUCH prefer using C++ over C# for Godot.

  • I don't like the strange performance, PascalCase and camelCase, and various quirks of the language.

  • C++ gives me more freedom inside the engine, with the possibility to contribute and customize Godot, and it is a more interesting challenge.

  • I didn't like the support for Godot at all, with many limitations and annoying issues.

  • I think the syntax is ugly and somewhat outdated.

About
  • Default:  Private / Internal.

  • "A lot of features you see now in C# were borrowed from Swift" - Person who made Mono.

  • There has been C# support since Godot 3.0.

Status
  • (2024-11-21) "There's work right now to move CSharp to GDExtension".

  • Limitations .

  • CSharp in Godot, with .NET 8 .

  • Problems :

    • Problems .

      • Writing editor plugins is possible, but it is currently quite convoluted.

      • State is currently not saved and restored when hot-reloading, except for exported variables.

      • Attached C# scripts should refer to a class whose class name matches the file name.

      • There are some methods such as Get() / Set() , Call() / CallDeferred()  and the signal connection method Connect()  that rely on Godot's snake_case  API naming conventions. So when using e.g. CallDeferred("AddChild") , AddChild  will not work because the API expects the original snake_case  version add_child .

    • Modifying values:

      • You might encounter the following error when trying to modify some values in Godot objects, e.g., when trying to change the X coordinate of a Node2D :

      public partial class MyNode2D : Node2D
      {
          public override void _Ready()
          {
              Position.X = 100.0f;
              // CS1612: Cannot modify the return value of 'Node2D.Position' because
              // it is not a variable.
          }
      }
      
      • Structs (in this example, a Vector2 ) in C# are copied on assignment, meaning that when you retrieve such an object from a property or an indexer, you get a copy of it, not the object itself. Modifying said copy without reassigning it afterwards won't achieve anything.

      • The workaround is simple: retrieve the entire struct, modify the value you want to change, and reassign the property.

      var newPosition = Position;
      newPosition.X = 100.0f;
      Position = newPosition;
      
      • Since C# 10, it is also possible to use with expressions  on structs, allowing you to do the same thing in a single line.

      Position = Position with { X = 100.0f };
      
      • Sometimes this boilerplate must be done to improve C# performance compared to GDScript, as explained .

    • Unsupported or invalid code .

    • C# GC (Garbage Collector) issues .

      • When things accumulate, a Stop The World occurs to clean everything.

        • No GC language can fully solve this problem.

      • Band-aids to minimize garbage accumulation to avoid GC issues:

        • Do not allocate objects during gameplay.

          • Doesn't always solve it.

        • "Just pool objects".

        • "Collect on every scene load".

          • "Clears every scene change, it's fine".

Building
  • You need to (re)build the project assemblies whenever you want to see new exported variables or signals in the editor. This build can be manually triggered by clicking the Build  button in the top right corner of the editor.

  • You will also need to rebuild the project assemblies to apply changes in "tool" scripts.

API Differences
  • Documentation .

    • wow.... so much bad stuff.

  • @GlobalScope

    • Functions normally in global scope in GDScript, like Godot's print  function, are available in the GD  static class which is part of the Godot  namespace.

      • GD.Print("Hello from C# to Godot");